package com.jinxinol.core.util.http;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.Map;

import com.jinxinol.core.util.StringUtils;



/**
 * <p>发出一个Http请求，并获得返回结果。</p>
 * 
 */
public class HttpRequester {

	/**
	 * <p>缺省的字符集。</p>
	 */
	private String defaultContentEncoding = "UTF-8"; 
	
	/**
	 * <p>连接对象。</p>
	 */
	private HttpURLConnection urlConnection = null;
	
	/**
	 * <p>临时文件所在路径。</p>
	 */
	private String fileLocation;

	/**
	 * <p>构造方法。</p>
	 */
	public HttpRequester() {
		super();
	}

	/**
	 * <p>发起GET方式的请求，无参数。</p>
	 *
	 * @param urlString url字符串。
	 * @return HttpResponser 返回结果。
	 * @throws IOException IO异常。
	 */
	public HttpResponser sendGet(String urlString) throws IOException {  
		return this.send(urlString, "GET", null, null);  
	} 

	/**
	 * <p>发起GET方式的请求，有参数。</p>
	 *
	 * @param urlString url字符串。
	 * @param params 参数集合。
	 * @return HttpResponser 返回结果。
	 * @throws IOException IO异常。
	 */
	public HttpResponser sendGet(String urlString, Map<String, String> params) throws IOException {  
		return this.send(urlString, "GET", params, null);  
	} 

	/**
	 * <p>发起POST方式的请求。</p>
	 *
	 * @param urlString url字符串。
	 * @param params 参数集合。
	 * @return HttpResponser 返回结果。
	 * @throws IOException IO异常。
	 */
	public HttpResponser sendPost(String urlString, Map<String, String> params) throws IOException {  
		return this.send(urlString, "POST", params, null);  
	}  
	
	/**
	 * <p>发起POST方式的请求。</p>
	 *
	 * @param urlString url字符串。
	 * @param params 参数集合。
	 * @param propertys 属性集合。
	 * @return HttpResponser 返回结果。
	 * @throws IOException IO异常。
	 */
	public HttpResponser sendPost(String urlString, Map<String, String> params, Map<String, String> propertys) throws IOException {  
		return this.send(urlString, "POST", params, propertys);  
	}  	
	
	/**
	 * <p>发起请求。</p>
	 *
	 * @param urlString url字符串。
	 * @param method 请求方式。
	 * @param parameters 参数集合。
	 * @param propertys 属性集合。
	 * @return HttpResponser 返回结果。
	 * @throws IOException IO异常。
	 */
	private HttpResponser send(String urlString, String method, Map<String, String> parameters, Map<String, String> propertys) throws IOException {  
 
		// 如果请求为GET方式，则将参数拼接到URL字符串的后面
		if (method.equalsIgnoreCase("GET") && parameters != null) {  
			StringBuffer param = new StringBuffer();  
			int i = 0;  
			for (String key : parameters.keySet()) {  
				param.append((i==0)?"?":"&").append(key).append("=").append(parameters.get(key));  
				i++;  
			}  
			urlString += param;  
		}  

		URL url = new URL(urlString);  

		// 创建连接并设置连接参数
		urlConnection = (HttpURLConnection)url.openConnection();  
		urlConnection.setRequestMethod(method);  
		urlConnection.setDoOutput(true);  
		urlConnection.setDoInput(true);  
		urlConnection.setUseCaches(false);  
    
		// 设置请求属性
		if (propertys != null) {  
			for (String key : propertys.keySet()) {  
				urlConnection.addRequestProperty(key, propertys.get(key));  
			}  
		}
    
		// 处理POST方式传送的参数
		if (method.equalsIgnoreCase("POST") && parameters != null) {  
			StringBuffer param = new StringBuffer();  
			for (String key : parameters.keySet()) {  
				param.append("&").append(key).append("=").append(parameters.get(key));  
			}  
			urlConnection.getOutputStream().write(param.toString().getBytes());  
			urlConnection.getOutputStream().flush();  
			urlConnection.getOutputStream().close();  
		}
    
		String ecod = urlConnection.getContentEncoding();  
		if (ecod == null)  
			ecod = this.defaultContentEncoding;  

		// 发起请求，并将返回结果存放到HttpResponser对象中
		HttpResponser httpResponser = new HttpResponser();  
		try {  
			InputStream in = urlConnection.getInputStream();  
			StringBuffer temp = new StringBuffer();  
			if (StringUtils.hasText(fileLocation)) {
				// 生成随机文件名
				Date date = new Date();
				long random = Math.round(Math.ceil(Math.random() * 10000 + 1));
				String randomName = fileLocation + String.valueOf(date.getTime() + random);
				File file = new File(randomName);
				if (!file.exists()) {
					file.createNewFile();
				}
				OutputStream out = new FileOutputStream(file);
				BufferedWriter output = new BufferedWriter(new FileWriter(file));
				byte[] buf = new byte[8192];
				int len = in.read(buf);
				while (len >= 0) {  
//					out.write(new String(buf, 0, len, ecod).getBytes(ecod));
					out.write(buf, 0, len);
					len = in.read(buf);
				}  
				output.flush();
				output.close();
				temp.append(randomName.toString());
			}
			else {
				byte[] buf = new byte[8192];
				int len = in.read(buf);
				while (len >= 0) {  
					temp.append(new String(buf, 0, len, ecod));
					len = in.read(buf);
				}  
			}

			httpResponser.urlString = urlString;  

			httpResponser.defaultPort = urlConnection.getURL().getDefaultPort();  
			httpResponser.file = urlConnection.getURL().getFile();  
			httpResponser.host = urlConnection.getURL().getHost();  
			httpResponser.path = urlConnection.getURL().getPath();  
			httpResponser.port = urlConnection.getURL().getPort();  
			httpResponser.protocol = urlConnection.getURL().getProtocol();  
			httpResponser.query = urlConnection.getURL().getQuery();  
			httpResponser.ref = urlConnection.getURL().getRef();  
			httpResponser.userInfo = urlConnection.getURL().getUserInfo();  

			httpResponser.content = temp.toString();  
			httpResponser.contentEncoding = ecod;  
			httpResponser.code = urlConnection.getResponseCode();  
			httpResponser.message = urlConnection.getResponseMessage();  
			httpResponser.contentType = urlConnection.getContentType();  
			httpResponser.method = urlConnection.getRequestMethod();  
			httpResponser.connectTimeout = urlConnection.getConnectTimeout();  
			httpResponser.readTimeout = urlConnection.getReadTimeout();  

			return httpResponser;  
		} catch (IOException e) {  
			throw e;  
		} finally {  
			if (urlConnection != null)  
				urlConnection.disconnect();  
		}
	}

	/**
	 * <p>返回fileLocation。</p>
	 *
	 * @return String
	 */
	public String getFileLocation() {
		return this.fileLocation;
	}

	/**
	 * <p>设置fileLocation。</p>
	 *
	 * @param fileLocation 要设置的
	 */
	public void setFileLocation(String fileLocation) {
		this.fileLocation = fileLocation;
	}  
}
